package tcln.sors.model.core.dao;

import java.util.Collection;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;

import tcln.sors.model.core.dom.Entity;
import ch.elca.el4j.services.persistence.hibernate.dao.ConvenienceGenericHibernateDao;

/**
 * Interface for a DAO in this application.
 * 
 * @param <E>
 *            Entity type.
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public interface Dao<E extends Entity<Integer>> extends ConvenienceGenericHibernateDao<E, Integer> {

    /**
     * Creates new instance of {@link DetachedCriteria} for queries.
     * 
     * @return new instance of {@link DetachedCriteria}.
     */
    DetachedCriteria createCriteria();

    /**
     * Gets an entity by its' ID. This method is different from {@link #findById(java.io.Serializable)} in that it
     * doesn't throw runtime exception if given entity doesn't exist. Instead, it returns <code>null</code>.
     * 
     * @param id
     *            entity id.
     * @return Entity or <code>null</code> if no entity is found.
     */
    E findByIdWeak(Integer id);

    /**
     * Flushes and clears current Hibernate session cache.
     * 
     * @return current instance.
     */
    Dao<E> flushSession();

    /**
     * Deletes all entities except given excluded entity IDs. This method is supposed to affect directly on the data
     * source and no hibernate/JPA cascading constrant is processed.
     * 
     * @param excludedEntityIds
     */
    void deleteOthers(Integer... excludedEntityIds);

    /**
     * Finds entities by their IDs.
     * 
     * @param ids
     *            All IDs of entities to be found.
     * @return
     */
    List<E> findByIds(Integer... ids);

    /**
     * Finds entities by their IDs.
     * 
     * @param ids
     *            All IDs of entities to be found.
     * @return
     */
    List<E> findByIds(Collection<Integer> ids);

    /**
     * Returns the maximum value for a given entity's property in the datastore.
     * 
     * @param <O>
     * @param property
     *            Property to get max value.
     * @return
     */
    <O> O max(String property);

    /**
     * Saves or updates all elements in given entity list.
     * 
     * @param entities
     * @return
     */
    List<E> saveOrUpdate(List<E> entities);

    /**
     * Merges a given detached (non-persisted) entity into current Session.
     * 
     * @param entity
     * @return Merged entity, usually the session-realized entity.
     */
    E merge(E entity);
}
